﻿using FFmpegVideoClip.Lib;
using SearchInFiles.Global;
using SearchInFiles.Lib.OpenFile;
using SearchInFiles.Lib.Tools;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace SearchInFiles.Lib.Search
{
    public class Search
    {
        private static bool IFilterSearch(FileElements.FileElement DocumentElenemt, ISearcher searcher)
        {
            if (DocumentElenemt.EnableIFilter && ReadDocument.IFilterTextReader(new FileInfo(DocumentElenemt.Path), out string Result))
                return searcher.Search(new(Result, DocumentElenemt));
            return false;
        }
        public static void SearchElement(FileElements.FileElement DocumentElenemt, HashSet<string> TextTypes, ISearcher searcher) 
        {
            if (TextTypes.Contains(DocumentElenemt.ExtensionTyep))
                DocumentElenemt.IsSearchHit = ReadDocument.ReadTextDocument(DocumentElenemt, searcher);
            else if (DocumentElenemt.ExtensionTyep.Equals(".doc", StringComparison.OrdinalIgnoreCase) || DocumentElenemt.ExtensionTyep.Equals(".docx", StringComparison.OrdinalIgnoreCase))
            {
                if (!IFilterSearch(DocumentElenemt, searcher))
                    DocumentElenemt.IsSearchHit = ReadDocument.ReadWord(DocumentElenemt, searcher);
            }
            else if (DocumentElenemt.ExtensionTyep.Equals(".xls", StringComparison.OrdinalIgnoreCase) || DocumentElenemt.ExtensionTyep.Equals(".xlsx", StringComparison.OrdinalIgnoreCase))
            {
                if (!IFilterSearch(DocumentElenemt, searcher))
                    DocumentElenemt.IsSearchHit = ReadDocument.ReadExcel(DocumentElenemt, searcher);
            }
            else if (DocumentElenemt.ExtensionTyep.Equals(".ppt", StringComparison.OrdinalIgnoreCase) || DocumentElenemt.ExtensionTyep.Equals(".pptx", StringComparison.OrdinalIgnoreCase))
            {
                if (!IFilterSearch(DocumentElenemt, searcher))
                    DocumentElenemt.IsSearchHit = ReadDocument.ReadPowerPoint(DocumentElenemt, searcher);
            }
            else if (DocumentElenemt.ExtensionTyep.Equals(".vsd", StringComparison.OrdinalIgnoreCase) || DocumentElenemt.ExtensionTyep.Equals(".vsdx", StringComparison.OrdinalIgnoreCase))
            {
                if (!IFilterSearch(DocumentElenemt, searcher))
                    DocumentElenemt.IsSearchHit = ReadDocument.ReadVisio(DocumentElenemt, searcher);
            }
            else if (DocumentElenemt.ExtensionTyep.Equals(".pdf", StringComparison.OrdinalIgnoreCase))
            {
                if (!IFilterSearch(DocumentElenemt, searcher))
                    DocumentElenemt.IsSearchHit = ReadDocument.ReadPdf(DocumentElenemt, searcher);
            }
            else if (DocumentElenemt.ExtensionTyep.Equals(".epub", StringComparison.OrdinalIgnoreCase))
            {
                if (!IFilterSearch(DocumentElenemt, searcher))
                    DocumentElenemt.IsSearchHit = ReadDocument.ReadEpub(DocumentElenemt, searcher);
            }
            else if (ReadDocument.IFilterTextReader(new FileInfo(DocumentElenemt.Path), out string Result))
                DocumentElenemt.IsSearchHit = searcher.Search(new(Result, DocumentElenemt));
            else DocumentElenemt.IsSupport = false;
        }
        public static async Task<int> SearchElementsAsync(ISearcher searcher, CancellationTokenSource cancellationTokenSource, ProgressBar progressBar) => await Task.Run(() =>
        {
            IEnumerable<FileElements.FileElement> elements = FileElements.Instance.AllValidSelectFiles;
            
            int progress = 0;
            int max = elements.Count(); ;
            if (max < 1)
                return 0;
            IProgress<int> progressHelp = null!;
            progressBar.Dispatcher.Invoke(() => { progressBar.Maximum = max; progressHelp = new Progress<int>(p => progressBar.Value = p); });
            try
            {
                UtilityTools.SetParallelMode(elements, cancellationTokenSource, 5, UtilityTools.AvailableProcessorCount()).AsUnordered()
                    .ForAll(p =>
                    {
                        SearchElement(p, Config.Instance.TextFileTypesSet, searcher);
                        progressHelp.Report(Interlocked.Increment(ref progress));
                    });
            }
            catch (OperationCanceledException) { }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder();
                Exception? exception = ex;
                while (exception != null)
                {
                    sb.AppendLine(exception.ToString());
                    exception = exception.InnerException;
                }
                MessageBoxEx.Show(App.Current.MainWindow, sb.ToString(), "搜索文件异常", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
            }
            searcher.Sort();
            return searcher.ResultCount;
        });
    }
    
}
